package com.bai;

import com.bai.utils.ParseUtils;

import java.io.*;
import java.lang.reflect.Field;
import java.text.MessageFormat;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class createByTemplate {

    private static final String FILE_BASIC_PATH = "D:\\Dev\\WorkSpcae-Idea\\mybatils\\src\\main\\resources\\temp";

    private static final String CONTROLLER_PATH = "\\controller\\TemplateController.java.tp";
    private static final String MANAGER_PATH = "\\manager\\TemplateManager.java.tp";
    private static final String MANAGER_IMPL_PATH = "\\manager\\Impl\\TemplateManagerImpl.java.tp";
    private static final String ADD_JS_PATH = "\\view\\template\\js\\addTemplate.js.tp";
    private static final String EDIT_JS_PATH = "\\view\\template\\js\\editTemplate.js.tp";
    private static final String LIST_JS_PATH = "\\view\\template\\js\\templateList.js.tp";
    private static final String ADD_JSP_PATH = "\\view\\template\\jsp\\addTemplate.jsp.tp";
    private static final String EDIT_JSP_PATH = "\\view\\template\\jsp\\editTemplate.jsp.tp";
    private static final String LIST_JSP_PATH = "\\view\\template\\jsp\\templateList.jsp.tp";

    private static final String SAVE_PATH = "C:\\Users\\Felix.Bai\\Desktop\\SAVE";

    private static List<String> filePaths = new ArrayList<String>();

    private static String TEMPLATE_FILE_NAME_UPPER_FIRST = "Template";//首字母大写
    private static String TEMPLATE_FILE_NAME_LOWER_FIRST = "template";//首字母小写
    private static String TEMPLATE_FILE_SUFFIX = ".tp";//文件后缀

    private static String className = null;
    private static String tableName = null;
    private static String newEntityName = null;
    private static String classDescription = null;
    private static String now = null;



    static {
        filePaths.add(CONTROLLER_PATH);
        filePaths.add(MANAGER_PATH);
        filePaths.add(MANAGER_IMPL_PATH);
        filePaths.add(ADD_JS_PATH);
        filePaths.add(EDIT_JS_PATH);
        filePaths.add(LIST_JS_PATH);
        filePaths.add(ADD_JSP_PATH);
        filePaths.add(EDIT_JSP_PATH);
        filePaths.add(LIST_JSP_PATH);


        if(!new File(FILE_BASIC_PATH).exists()){
            System.out.println("模板加载出错！");
        }

        if(!new File(SAVE_PATH).exists()){
            new File(SAVE_PATH).mkdir();
            System.out.println("保存目录创建成功！");
        }

    }

    public static void main(String[] args) {
        //generateFileByTemplate(FeeRecord.class,"费用记录");
    }



    /**
     * 根据模板生成这个类得Controller、Manager、js、jsp
     * @param clazz
     * @param classDesc
     */
    private static void generateFileByTemplate(Class clazz,String classDesc) {
        Map<String,String> params = getClassInfo(clazz,classDesc);
        if(filePaths != null && filePaths.size() > 0){
            for (String filePath:filePaths) {
                generateFile(filePath,params);
            }
        }

    }

    /**
     * 开始构建和生成文件
     * @param filePath
     * @param params
     */
    private static void generateFile(String filePath,Map<String,String> params) {
        String template = readFileByChars(FILE_BASIC_PATH + filePath);
        String generateContents = processTemplate(template,params);
        //修改文件目录和文件名字
        filePath = filePath
                .replaceAll(TEMPLATE_FILE_NAME_UPPER_FIRST,params.get("className"))
                .replaceAll(TEMPLATE_FILE_NAME_LOWER_FIRST,params.get("newEntityName"))
                .replaceAll(TEMPLATE_FILE_SUFFIX,"");
        appendFile(SAVE_PATH + filePath,generateContents);
    }


    public static Map<String,String> getClassInfo(Class clazz,String classDesc) {
        Map<String,String> map = new HashMap<String,String>();
        className = clazz.getSimpleName();
        tableName = ParseUtils.formatToSqlName(className).substring(1);
        newEntityName = ParseUtils.lowerFirst(className);//新实例名字
        classDescription = classDesc;
        now = new SimpleDateFormat("yyyy年MM月dd日 HH:mm:ss").format(new Date());

        map.put("className",className);
        map.put("tableName",tableName);
        map.put("newEntityName",newEntityName);
        map.put("classDescription",classDescription);
        map.put("now",now);
        return map;
    }

    /**
     * 以字符为单位读取文件，常用于读文本，数字等类型的文件
     */
    public static String readFileByChars(String fileName) {
        StringBuffer contents = new StringBuffer();
        File file = new File(fileName);
        Reader reader = null;
        /*try {
            System.out.println("以字符为单位读取文件内容，一次读一个字节：");
            // 一次读一个字符
            reader = new InputStreamReader(new FileInputStream(file));
            int tempchar;
            while ((tempchar = reader.read()) != -1) {
                // 对于windows下，\r\n这两个字符在一起时，表示一个换行。
                // 但如果这两个字符分开显示时，会换两次行。
                // 因此，屏蔽掉\r，或者屏蔽\n。否则，将会多出很多空行。
                if (((char) tempchar) != '\r') {
                    System.out.print((char) tempchar);
                }
            }
            reader.close();
        } catch (Exception e) {
            e.printStackTrace();
        }*/
        try {
            //System.out.println("以字符为单位读取文件内容，一次读多个字节：");
            // 一次读多个字符
            char[] tempchars = new char[30];
            int charread = 0;
            reader = new InputStreamReader(new FileInputStream(fileName));
            // 读入多个字符到字符数组中，charread为一次读取字符数
            while ((charread = reader.read(tempchars)) != -1) {
                // 同样屏蔽掉\r不显示
                if ((charread == tempchars.length)
                        && (tempchars[tempchars.length - 1] != '\r')) {
                    //System.out.print(tempchars);
                    contents.append(tempchars);
                } else {
                    for (int i = 0; i < charread; i++) {
                        if (tempchars[i] == '\r') {
                            continue;
                        } else {
                            //System.out.print(tempchars[i]);
                            contents.append(tempchars[i]);
                        }
                    }
                }
            }

        } catch (Exception e1) {
            e1.printStackTrace();
        } finally {
            if (reader != null) {
                try {
                    reader.close();
                } catch (IOException e1) {
                }
            }

            return contents.toString();
        }
    }

    /**
     * 替换字符串模板(模板渲染)
     * @param template
     * @param params
     * @return
     */
    public static String processTemplate(String template, Map<String, String> params){
        StringBuffer sb = new StringBuffer();
        Matcher m = Pattern.compile("\\#\\[\\w+\\]\\#").matcher(template);
        while (m.find()) {
            String param = m.group();
            String value = params.get(param.substring(2, param.length() - 2));
            m.appendReplacement(sb, value==null ? "" : value);
        }
        m.appendTail(sb);
        return sb.toString();
    }

    /**
     * 追加文件：使用FileWriter
     * @param fileName
     * @param content
     */
    public static void appendFile(String fileName, String content) {
        try {
            checkFilePath(fileName);
            //打开一个写文件器，构造函数中的第二个参数true表示以追加形式写文件
            FileWriter writer = new FileWriter(fileName);
            PrintWriter printWriter = new PrintWriter(writer);
            printWriter.println(content);
            //writer.write(content);
            writer.close();
            System.out.println(fileName.substring(fileName.lastIndexOf("\\")+1)+"生成成功，路径为："+fileName);
        } catch (IOException e) {
            e.printStackTrace();
        }

    }

    /**
     * 检查文件目录和文件
     * @param fileName
     * @return
     */
    public static void checkFilePath(String fileName){
        File fileDirectory = new File(fileName.substring(0,fileName.lastIndexOf("\\")));
        File file = new File(fileName);

        try {
            if (!fileDirectory.exists() || !file.exists()) {
                fileDirectory.mkdirs();
                file.createNewFile();
            }
        }catch (IOException e) {
            System.out.println("新建文件操作出错");
            e.printStackTrace();
        }
    }

}
